home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-31 | 14.2 KB | 545 lines | [TEXT/MMCC] |
- /**************************************************************************
- LGBIconButton
-
- Public domain, by Zig Zichterman.
-
- This class implements 3D icon push buttons according to the guidelines
- suggested in _develop_ 15. Some of the drawing code is taken from
- the public domain source accompanying _develop_ 15.
-
- A new button variant that draws an icon button. The icon draws
- in a rectangular frame with 3D effects.
-
- LGBIconButton uses contrlValue for the resource id of the icon family.
- You must set contrlValue (and probably contrlMax).
-
- LGBIconButton does not draw a title. Ever. Since it is bad HI to
- display an icon without an accompanying text, you should place a
- caption near this button to clue the user in to just what your
- icon means.
-
- 07/31/94 zz Draw 3D if 4-bit grey, BW if 4-bit color
- 07/31/94 zz save/restore pen colors
- 1.0b2 (never released)
- 07/20/94 zz call PenNormal() before drawing anything!
- 1.0b1
- **************************************************************************/
- #include "LGBIconButton.h"
-
- #include <GestaltEqu.h>
- #include <Icons.h>
-
- #include "LGBControl.h"
- #include "LGBDeviceIterator.h"
- #include "UGBDraw.h"
-
- /**************************************************************************
- Main() [static]
-
- Main entry point for all icon push button calls. Dispatch according to
- message.
- **************************************************************************/
- long
- LGBIconButton::Main(short inVariation, ControlHandle ioControl,
- short inMsg, long ioParam)
- {
- long returnMe = 0;
-
- // lock the control handle for the duration of this call
- char state = ::HGetState((Handle) ioControl);
- ::HLock((Handle) ioControl);
-
- LGBIconButton button(*ioControl);
-
- switch (inMsg) {
- case drawCntl :
- button.Draw(ioParam);
- break;
-
- case testCntl :
- {
- Point hitPt;
- hitPt.h = LoWord(ioParam);
- hitPt.v = HiWord(ioParam);
- if (button.Test(hitPt)) {
- returnMe = inButton;
- }
- }
- break;
-
- case calcCRgns : // only called in 24-bit mode
- { // is 32-bit addressing off?
- long result = 0;
- OSErr err = ::Gestalt(gestaltAddressingModeAttr,&result);
- if (!err && ((result &
- (1L << gestalt32BitAddressing)) == 0)) {
- RgnHandle rgn = (RgnHandle)
- ::StripAddress((Ptr) ioParam);
- button.CalcCRgn(rgn);
- }
- }
- break;
-
- case calcCntlRgn : // only called in 32-bit mode
- {
- button.CalcCRgn((RgnHandle) ioParam);
- }
- break;
- }
-
- // unlock handle
- ::HSetState((Handle) ioControl,state);
- return returnMe;
- }
-
- //—————————————————————————————————————————————————————————————————————————
- // Constructor
- //—————————————————————————————————————————————————————————————————————————
-
- /**************************************************************************
- LGBControl(ControlHandle,Boolean)
-
- construct/initialize a control object. Just stash the control
- handle away for the rest of the class to toy with.
- **************************************************************************/
- LGBIconButton::LGBIconButton(ControlRecord *inControl)
- : mControl(inControl)
- {
-
- }
-
- //—————————————————————————————————————————————————————————————————————————
- // Dispatch entry points
- //—————————————————————————————————————————————————————————————————————————
-
- /**************************************************************************
- Draw()
-
- Draw the control. inPartCode is a part code specifying which part of
- the control to draw, or 0 for the entire control.
-
- icon buttons only have inButton, so we ignore the inPartCode.
-
- Save the current drawing environment. Iterate through all the devices
- (screens), drawing the control in color or black and white depending
- on the screen depth. Once done, restore the drawing environment and
- return.
- **************************************************************************/
- void
- LGBIconButton::Draw(long inPartCode)
- {
- // if we're invisible, don't draw
- if (mControl->contrlVis == false) return;
-
- // save the pen colors // will probably crash SEs, so test first
- RGBColor fore,back;
- if (UGBDraw::ColorQDIsPresent()) {
- ::GetForeColor(&fore);
- ::GetBackColor(&back);
- }
-
- // save the clip region
- RgnHandle saveClip = ::NewRgn();
- if (!saveClip) return;
- ::GetClip(saveClip);
-
- // make the pen something sensible
- ::PenNormal();
- ::ForeColor(blackColor);
- ::BackColor(whiteColor);
-
- // loop through all the devices
- LGBDeviceIterator device;
- device.Init(mControl->contrlRect);
- short depth = 0;
- do {
- depth = device.Next();
- if (depth == 0) break; // all done with devices
- if ((depth < 4)
- || (depth == 4 && device.mDeviceIsColor)) {
- DrawBW();
- } else {
- DrawColor();
- }
- } while(true);
-
- // restore the pen
- if (UGBDraw::ColorQDIsPresent()) {
- ::RGBForeColor(&fore);
- ::RGBBackColor(&back);
- }
-
- // restore the clip region
- ::SetClip(saveClip);
- ::DisposeRgn(saveClip);
- }
-
- /**************************************************************************
- Test()
-
- Return inButton if the point is in our rect,
- **************************************************************************/
- Boolean
- LGBIconButton::Test(Point inHitPt)
- {
- return ::PtInRect(inHitPt,&(mControl->contrlRect));
- }
-
- /**************************************************************************
- CalcCRgn()
-
- Calculate the control's region in the given region handle
- **************************************************************************/
- void
- LGBIconButton::CalcCRgn(RgnHandle ioRgn)
- {
- if (!ioRgn) return; // idiot resistance
- ::RectRgn(ioRgn,&(mControl->contrlRect));
- }
-
- //—————————————————————————————————————————————————————————————————————————
- // Draw
- //—————————————————————————————————————————————————————————————————————————
-
- /**************************************************************************
- DrawBW()
-
- Draw the control in black and white
- **************************************************************************/
- void
- LGBIconButton::DrawBW(void)
- {
- // Set the pen to black, 1x1
- ::PenNormal();
-
- // erase the insides
- EraseInsides();
-
- // draw the frame
- DrawFrame();
-
- // draw the icon
- DrawIcon(false);
-
- // draw the monochrome 3D effects
- DrawBW3D();
-
- // draw highlight if necessary
- const short hilite = mControl->contrlHilite;
- if (hilite && (hilite != 255)) {
- Rect invertMe = mControl->contrlRect;
- ::InsetRect(&invertMe,1,1);
- ::InvertRect(&invertMe);
- }
- }
-
- /**************************************************************************
- DrawBW3D()
-
- Draw the 3D effects as a 50% grey dither on the bottom right sides
- **************************************************************************/
- void
- LGBIconButton::DrawBW3D(void)
- {
- // no 3D on inactive buttons
- if (mControl->contrlHilite == 255) return;
-
- // fabricate a 50% grey pattern on the fly rather
- // than hassle with QD globals and A4 stuff
- unsigned char grey[8];
- grey[0] = grey[2] = grey[4] = grey[6] = 0xAA;
- grey[1] = grey[3] = grey[5] = grey[7] = 0x55;
- ::PenPat((PatPtr) grey);
-
- Rect box = mControl->contrlRect;
- ::MoveTo(box.right - 2, box.top + 1);
- ::LineTo(box.right - 2, box.bottom - 2);
- ::MoveTo(box.right - 3, box.top + 2);
- ::LineTo(box.right - 3, box.bottom - 3);
-
- ::MoveTo(box.left + 1, box.bottom - 2);
- ::LineTo(box.right - 2, box.bottom - 2);
- ::MoveTo(box.left + 2, box.bottom - 3);
- ::LineTo(box.right - 3, box.bottom - 3);
-
- ::PenNormal();
- }
-
- /**************************************************************************
- DrawFrame()
-
- Draw the button frame--it's a rect with the corner pixels knocked out
- **************************************************************************/
- void
- LGBIconButton::DrawFrame(void)
- {
- Rect box = mControl->contrlRect;
- ::MoveTo(box.left + 1,box.top);
- ::LineTo(box.right - 2, box.top);
- ::MoveTo(box.right - 1, box.top + 1);
- ::LineTo(box.right - 1, box.bottom - 2);
- ::MoveTo(box.right - 2, box.bottom - 1);
- ::LineTo(box.left + 1, box.bottom - 1);
- ::MoveTo(box.left, box.bottom - 2);
- ::LineTo(box.left, box.top + 1);
- }
-
- /**************************************************************************
- EraseInsides()
- **************************************************************************/
- void
- LGBIconButton::EraseInsides(void)
- {
- Rect box = mControl->contrlRect;
- ::InsetRect(&box,1,1);
- ::EraseRect(&box);
- }
-
- /**************************************************************************
- DrawIcon()
- **************************************************************************/
- void
- LGBIconButton::DrawIcon(Boolean inColor)
- {
- Rect iconRect = mControl->contrlRect;
- ::InsetRect(&iconRect,4,4);
-
- short iconID = mControl->contrlValue;
- short align = atNone; // atVerticalCenter | atHorizontalCenter;
- short transform = ttNone;
- const short hilite = mControl->contrlHilite;
- if (hilite == 255) {
- transform = ttDisabled;
- } else if (hilite) {
- if (inColor) {
- transform = ttSelected;
- }
- }
-
- ::PlotIconID(&iconRect,align,transform,iconID);
- }
-
- /**************************************************************************
- DrawColor()
-
- Draw the control in color, either active or inactive
- **************************************************************************/
- void
- LGBIconButton::DrawColor(void)
- {
- if (mControl->contrlHilite == 255) {
- DrawColorInactive();
- } else {
- DrawColorActive();
- }
-
- // restore the pen
- ::PenNormal();
- UGBDraw::PenReallyNormal();
- }
-
- /**************************************************************************
- DrawColorInactive()
-
- Draw the control in color, inactive. It's flattened out (no 3D
- effects), and uses a greyer shade of pale for the frame.
- **************************************************************************/
- void
- LGBIconButton::DrawColorInactive(void)
- {
- UGBDraw::PenFrameInactive();
- DrawFrame();
-
- UGBDraw::Background();
- EraseInsides();
-
- DrawIcon();
- }
-
- /**************************************************************************
- DrawColorActive()
-
- Draw the control in color, active. Draw 3D effects.
- **************************************************************************/
- void
- LGBIconButton::DrawColorActive(void)
- {
- UGBDraw::PenFrameActive();
- DrawFrame();
-
-
- if (mControl->contrlHilite) {
- // setup background color for highlighted fill
- UGBDraw::BackGrey(UGBDraw_grey8);
- } else {
- // setup background color for normal (unhighlighted) fill
- UGBDraw::Background();
- }
- EraseInsides();
-
- DrawIcon();
-
- Draw3DEffects();
- }
-
- /**************************************************************************
- Draw3DEffects()
-
- Draw the spiffy 3D effects. This function should only be called
- when 1) you know you have 8 or more bits of color, and 2) the
- button is active
- **************************************************************************/
- void
- LGBIconButton::Draw3DEffects(void)
- {
- if (mControl->contrlHilite) { // draw highlighted
- { // ouside edge
- Rect box = mControl->contrlRect;
- ::InsetRect(&box,1,1);
-
- // top left shadow
- UGBDraw::ForeGrey(UGBDraw_grey4);
- ::MoveTo(box.left, box.bottom - 2);
- ::LineTo(box.left, box.top);
- ::LineTo(box.right - 2, box.top);
-
- // bottom right unshadow
- UGBDraw::ForeGrey(UGBDraw_greyC);
- ::MoveTo(box.left, box.bottom - 1);
- ::LineTo(box.right - 1, box.bottom - 1);
- ::LineTo(box.right - 1, box.top);
-
- // top left corner
- UGBDraw::ForeGrey(UGBDraw_grey2);
- ::MoveTo(box.left, box.top);
- ::Line(0,0);
-
- // top right corner
- UGBDraw::ForeGrey(UGBDraw_grey7);
- ::MoveTo(box.right - 1, box.top);
- ::Line(0,0);
-
- // bottom left corner
- UGBDraw::ForeGrey(UGBDraw_grey7);
- ::MoveTo(box.left, box.bottom - 1);
- ::Line(0,0);
-
- // bottom right corner
- UGBDraw::ForeGrey(UGBDraw_greyC);
- ::MoveTo(box.right - 1, box.bottom - 1);
- ::Line(0,0);
- }
-
- { // inside edge
- Rect box = mControl->contrlRect;
- ::InsetRect(&box,2,2);
-
- // top left shadow
- UGBDraw::ForeGrey(UGBDraw_grey5);
- ::MoveTo(box.left, box.bottom - 2);
- ::LineTo(box.left, box.top);
- ::LineTo(box.right - 2, box.top);
-
- // bottom right unshadow
- UGBDraw::ForeGrey(UGBDraw_greyA);
- ::MoveTo(box.left, box.bottom - 1);
- ::LineTo(box.right - 1, box.bottom - 1);
- ::LineTo(box.right - 1, box.top);
-
- // top left corner
- UGBDraw::ForeGrey(UGBDraw_grey4);
- ::MoveTo(box.left, box.top);
- ::Line(0,0);
-
- // top right corner
- UGBDraw::ForeGrey(UGBDraw_grey8);
- ::MoveTo(box.right - 1, box.top);
- ::Line(0,0);
-
- // bottom left corner
- UGBDraw::ForeGrey(UGBDraw_grey8);
- ::MoveTo(box.left, box.bottom - 1);
- ::Line(0,0);
-
- // bottom right corner
- UGBDraw::ForeGrey(UGBDraw_greyD);
- ::MoveTo(box.right - 1, box.bottom - 1);
- ::Line(0,0);
- }
- } else { // draw unhighlighted
- { // ouside edge
- Rect box = mControl->contrlRect;
- ::InsetRect(&box,1,1);
-
- // top left unshadow
- UGBDraw::ForeGrey(UGBDraw_greyD);
- ::MoveTo(box.left, box.bottom - 2);
- ::LineTo(box.left, box.top);
- ::LineTo(box.right - 2, box.top);
-
- // bottom right shadow
- UGBDraw::ForeGrey(UGBDraw_grey7);
- ::MoveTo(box.left, box.bottom - 1);
- ::LineTo(box.right - 1, box.bottom - 1);
- ::LineTo(box.right - 1, box.top);
-
- // top left corner
- UGBDraw::ForeGrey(UGBDraw_greyF);
- ::MoveTo(box.left, box.top);
- ::Line(0,0);
-
- // top right corner
- UGBDraw::ForeGrey(UGBDraw_greyC);
- ::MoveTo(box.right - 1, box.top);
- ::Line(0,0);
-
- // bottom left corner
- UGBDraw::ForeGrey(UGBDraw_greyC);
- ::MoveTo(box.left, box.bottom - 1);
- ::Line(0,0);
-
- // bottom right corner
- UGBDraw::ForeGrey(UGBDraw_grey4);
- ::MoveTo(box.right - 1, box.bottom - 1);
- ::Line(0,0);
- }
-
- { // inside edge
- Rect box = mControl->contrlRect;
- ::InsetRect(&box,2,2);
-
- // top left shadow
- UGBDraw::ForeGrey(UGBDraw_greyF);
- ::MoveTo(box.left, box.bottom - 2);
- ::LineTo(box.left, box.top);
- ::LineTo(box.right - 2, box.top);
-
- // bottom right unshadow
- UGBDraw::ForeGrey(UGBDraw_grey8);
- ::MoveTo(box.left, box.bottom - 1);
- ::LineTo(box.right - 1, box.bottom - 1);
- ::LineTo(box.right - 1, box.top);
-
- // top left corner
- UGBDraw::ForeGrey(UGBDraw_greyF);
- ::MoveTo(box.left, box.top);
- ::Line(0,0);
-
- // top right corner
- UGBDraw::ForeGrey(UGBDraw_greyC);
- ::MoveTo(box.right - 1, box.top);
- ::Line(0,0);
-
- // bottom left corner
- UGBDraw::ForeGrey(UGBDraw_greyC);
- ::MoveTo(box.left, box.bottom - 1);
- ::Line(0,0);
-
- // bottom right corner
- UGBDraw::ForeGrey(UGBDraw_grey5);
- ::MoveTo(box.right - 1, box.bottom - 1);
- ::Line(0,0);
- }
- }
- }
-